1. Field of the Invention
The invention relates generally to means for testing microprocessors and more specifically to devices and methods for recording significant trace events in the execution of a software program in a trace history buffer and then using the trace history buffer to reconstruct the sequence of execution of the programs instructions.
2. Description of the Relevant Art
There are numerous problems involved in the development of integrated circuits (ICs) and devices which use ICs. Because of the increasing speed and complexity, as well as the decreasing size of ICs, designers face decreased access to the products for testing and increased amounts of time to perform the tests. It is becoming more and more difficult to test and debug the design and operation of these products but, when a new processor design is implemented, it must be debugged to ensure that it operates as expected. (Debugging is the process of finding and eliminating problems, or bugs, in hardware or software.)
Many of the designers' problems arise from the difficulty of using traditional testing at the IC level, board level and system level. The complexity of testing using traditional methods has grown commensurately with the complexity of the products themselves. For example, a large portion of the time required to implement a new microprocessor design is spent on debugging the design. The increased costs and the time required to debug and test can cause delays which disrupt manufacturing flows and hinder manufacturers' efforts to bring the products to market. Testing methods which can offset the complexity of the products are therefore desirable.
The time and expense associated with traditional testing methods have lead to the development of what are known as "design for test" methods. Design for test (DFT) methods actually comprise both design methodologies and testing methodologies. DFT methodologies incorporate certain design rules and techniques and also include implementation of specific test-related structures to allow for greater ease of testing. DFT methodologies may be implemented at IC, board and system levels. The facilitation of testing through DFT methodologies allows thorough testing of products which might otherwise be prohibitively expensive or time consuming. The use of DFT methodologies, although increasing the length of the design cycle and the cost of designing the products, results in overall time and cost savings because of improved capability to debug, test and maintain the products.
Individual manufacturers' implementations of embedded test circuitry have varied. Some manufacturers have chosen to use proprietary techniques and structures. The use of individualized and restricted implementations, of course, may be limited. In order to allow DFT methodologies to be more widely utilized and more efficient, some manufacturers have attempted to develop standards relating to DFT methodologies in order to allow the use of less specialized, less costly equipment and greater reuse of previously developed test data.
DFT methodologies can be used in conjunction with more traditional test methods and tools. Debugging tools may therefore be external to the processor, internal to the processor, or a combination of both. The external tools may include software debuggers and hardware tools such as logic analyzers. The inclusion of internal debug features, or even more general features which simply facilitate debugging within a processor, can be very helpful to the designer and manufacturer of the processor. They can also be helpful to developers of hardware and software which will be used in connection with the processor.
One method for debugging a microprocessor is to execute a known application or a simple piece of test code on the microprocessor and then observe the results to determine whether the code executed correctly. The results which should be produced by the test code are known. The code is executed and the results are compared to the anticipated results. If the test code produces a correct result, the microprocessor is assumed to have operated properly. Any incorrect or inconsistent results indicate that the microprocessor has functioned in error.
When execution of the test code produces an incorrect output, this output may result from improper execution of any one of the instructions in the code. It is therefore useful to be able to observe execution of each of the instructions or to trace the sequence of instruction which is executed. By observing the execution of each instruction, it can be determined whether the test code executed in the expected manner or whether, for example, the code took a branch which should not have been taken. The identification of these branches which are taken in error can help the designer determine the design error which lead to the taking of the branch.
Some prior art debugging applications allow the user to track execution of a piece of test code. These debugging applications typically execute the test code line by line and display information related to the instructions so that the user can track the execution of the test code. The applications may also display particular information about the system as each instruction is executed. For example, the application may show the contents of various registers to the user. Using these applications, a user can determine the sequence of instructions which were executed in the test code and can thereby determine whether the microprocessor is functioning as intended.
Prior art debugging applications can be stopped at selected points in the execution of the code by setting breakpoints or by allowing a certain number of instructions to be executed. The user may thereby be able to step through the test code, one instruction at a time. One of the problems with this type of debugging is that the application cannot back up to a previously executed instruction. That is, it cannot undo one or more previous instructions. If the user wishes to determine the exact sequence of instructions which led to the current point in the test code's execution, the user must re-execute the test code until it reaches the point of interest. This re-execution of the test code can result in wasted time and processing bandwidth, particularly if the test code is large or if it requires a great deal of time to execute.